const { app: electronApp } = require('electron');
const { autoUpdater } = require("electron-updater");
const { is } = require('ee-core/utils');
const { logger } = require('ee-core/log');
const { getMainWindow, setCloseAndQuit } = require('ee-core/electron');
const yaml = require('js-yaml');

/**
 * 自动升级
 * @class
 */
class AutoUpdaterService {
  constructor() {
    // 简化配置，使用固定URL避免路径处理错误
    // 修改：指向目录而非具体文件
    let updateServerUrl = 'http://111.231.209.141/update/';
    
    // 直接从process.env获取，不做复杂处理
    if (process.env.VITE_UPDATE_SERVER_URL) {
      updateServerUrl = process.env.VITE_UPDATE_SERVER_URL;
    }
    
    this.config = {
      windows: true, // 启用Windows更新
      macOS: true,   // 启用macOS更新
      linux: true,   // 启用Linux更新
      options: {
        provider: 'generic', 
        url: updateServerUrl
      },
    }
  }

  /**
   * 创建
   */
  create () {
    // 在create方法中记录日志，此时logger应该已经完全初始化
    logger.info('[autoUpdater] load');
    logger.info('[autoUpdater] Using update server URL:', this.config.options.url);
    
    const cfg = this.config;
    if ((is.windows() && cfg.windows) || (is.macOS() && cfg.macOS) || (is.linux() && cfg.linux)) {
      logger.info('[autoUpdater] platform enabled');
    } else {
      logger.warn('[autoUpdater] platform not enabled');
      return
    }

    const status = {
      error: -1,
      available: 1,
      noAvailable: 2,
      downloading: 3,
      downloaded: 4,
    }

    const version = electronApp.getVersion();
    logger.info('[autoUpdater] current version: ', version);
  
    // 设置下载服务器地址
    let server = cfg.options.url;
    let lastChar = server.substring(server.length - 1);
    server = lastChar === '/' ? server : server + "/";
    cfg.options.url = server;
    
    logger.info('[autoUpdater] setting feed URL: ', server);
  
    try {
      // 详细配置autoUpdater
      autoUpdater.autoDownload = false; // 禁用自动下载，由用户触发
      autoUpdater.allowDowngrade = false; // 禁止降级
      autoUpdater.logger = logger; // 设置日志记录器
      
      // 设置更多配置项，解决超时问题
      autoUpdater.requestHeaders = { "Cache-Control": "no-cache" }; // 禁用缓存
      autoUpdater.forceDevUpdateConfig = true; // 强制使用开发配置
      autoUpdater.autoInstallOnAppQuit = true; // 应用退出时自动安装
      autoUpdater.updateConfigPath = null; // 重置配置路径
      autoUpdater.currentVersion = '4.0.2'; // 强制设置当前版本
      
      // 打印electron-updater内部使用的版本号
      logger.info('[autoUpdater] 实际使用的版本号:', autoUpdater.currentVersion);
      logger.info('[autoUpdater] App Version:', electronApp.getVersion());
      
      // 设置应用名称和当前版本
      const appName = '拓信IM'; // 修改为与实际打包名称一致
      logger.info('[autoUpdater] App name: ', appName);
      
      // 配置更新源，必须指定provider为generic
      const options = {
        provider: 'generic',
        url: server,
        channel: 'latest',
        updaterCacheDirName: 'tuoliao-updater'
      };
      
      logger.info('[autoUpdater] Full options: ', JSON.stringify(options));
      autoUpdater.setFeedURL(options);
      
      // 强制检查HTTP而不是HTTPS
      process.env.ELECTRON_UPDATER_DISABLE_HTTPS_VERIFICATION = 'true';
      logger.info('[autoUpdater] Disabled HTTPS verification for updater');

      // 添加自定义处理逻辑，修复中文文件名问题
      const originalEmit = autoUpdater.emit;
      autoUpdater.emit = function(event, ...args) {
        if (event === 'update-available' && args[0]) {
          const info = args[0];
          logger.info('[autoUpdater] 检测到更新，原始信息:', JSON.stringify(info));
          
          // 修复文件URL
          if (info.files && info.files.length > 0) {
            info.files.forEach(file => {
              if (file.url && !file.url.startsWith('http')) {
                // 处理URL，确保中文字符被正确编码
                file.url = server + encodeURIComponent(file.url);
                logger.info('[autoUpdater] 修复后的文件URL:', file.url);
              }
            });
          }
          
          // 修复路径
          if (info.path && typeof info.path === 'string') {
            logger.info('[autoUpdater] 原始路径:', info.path);
            info.path = info.path.replace(/[\u4e00-\u9fa5]/g, (match) => {
              return encodeURIComponent(match);
            });
            logger.info('[autoUpdater] 修复后的路径:', info.path);
          }
        }
        
        return originalEmit.call(this, event, ...args);
      };
    } catch (error) {
      logger.error('[autoUpdater] setFeedURL error : ', error);
    }
  
    autoUpdater.on('checking-for-update', () => {
      //sendStatusToWindow('正在检查更新...');
    })
    autoUpdater.on('update-available', (info) => {
      // 这个事件会在我们的自定义emit拦截器处理后触发
      const data = {
        status: status.available,
        desc: '有可用更新',
        version: info.version,
        releaseNotes: info.releaseNotes,
        // 添加文件信息，帮助调试
        files: info.files ? JSON.stringify(info.files) : '无文件信息',
        path: info.path || '无路径信息'
      }
      logger.info('[autoUpdater] 更新信息处理完成:', JSON.stringify(data));
      this.sendStatusToWindow(data);
    })
    autoUpdater.on('update-not-available', () => {
      const data = {
        status: status.noAvailable,
        desc: '没有可用更新'
      }
      this.sendStatusToWindow(data);
    })
    autoUpdater.on('error', (err) => {
      const data = {
        status: status.error,
        desc: err
      }
      this.sendStatusToWindow(data);
    })
    autoUpdater.on('download-progress', (progressObj) => {
      const percentNumber = parseInt(progressObj.percent);
      const totalSize = this.bytesChange(progressObj.total);
      const transferredSize = this.bytesChange(progressObj.transferred);
      let text = '已下载 ' + percentNumber + '%';
      text = text + ' (' + transferredSize + "/" + totalSize + ')';
  
      const data = {
        status: status.downloading,
        desc: text,
        percentNumber,
        totalSize,
        transferredSize
      }
      logger.info('[autoUpdater] progress: ', text);
      this.sendStatusToWindow(data);
    })
    autoUpdater.on('update-downloaded', () => {
      const data = {
        status: status.downloaded,
        desc: '下载完成'
      }
      this.sendStatusToWindow(data);

      // 托盘插件里面设置了阻止窗口关闭，这里设置允许关闭窗口
      setCloseAndQuit(true);
      
      // Install updates and exit the application
      autoUpdater.quitAndInstall();
    });
  }

  /**
   * 检查更新
   */
  checkUpdate () {
    try {
      // 使用配置中的URL，不再调用已弃用的getFeedURL方法
      const configUrl = this.config.options.url;
      logger.info('======== 更新配置信息 ========');
      logger.info('[autoUpdater] 更新服务器URL:', configUrl);
      logger.info('[autoUpdater] 当前应用版本:', electronApp.getVersion());
      logger.info('[autoUpdater] autoDownload设置:', autoUpdater.autoDownload);
      logger.info('[autoUpdater] allowDowngrade设置:', autoUpdater.allowDowngrade);
      logger.info('==============================');

      // 发送开始检查的状态到窗口
      this.sendStatusToWindow({
        status: 0, // 新增状态码：开始检查
        desc: '正在检查更新...',
        url: configUrl
      });

      // 手动获取latest.yml文件并解析
      this.fetchLatestYml(configUrl + 'latest.yml')
        .then(ymlContent => {
          logger.info('[autoUpdater] 成功获取latest.yml文件');
          
          try {
            // 尝试解析YML内容
            const yaml = require('js-yaml');
            const updateInfo = yaml.load(ymlContent);
            logger.info('[autoUpdater] 解析更新信息:', JSON.stringify(updateInfo));
            
            // 比较版本号
            const currentVersion = autoUpdater.currentVersion || electronApp.getVersion();
            logger.info('[autoUpdater] 当前版本:', currentVersion);
            logger.info('[autoUpdater] 最新版本:', updateInfo.version);
            
            if (this.isVersionNewer(updateInfo.version, currentVersion)) {
              logger.info('[autoUpdater] 发现新版本!');
              
              // 模拟update-available事件
              const info = {
                version: updateInfo.version,
                files: updateInfo.files,
                path: updateInfo.path,
                releaseDate: updateInfo.releaseDate,
                releaseNotes: updateInfo.releaseNotes || '此版本包含新功能和bug修复。'
              };
              
              // 发送更新可用状态
              const data = {
                status: 1, // 有可用更新
                desc: '有可用更新',
                version: info.version,
                releaseNotes: info.releaseNotes,
                files: JSON.stringify(info.files),
                path: info.path
              };
              
              this.sendStatusToWindow(data);
            } else {
              logger.info('[autoUpdater] 已经是最新版本');
              
              // 发送无更新状态
              this.sendStatusToWindow({
                status: 2, // 无可用更新
                desc: '已经是最新版本'
              });
            }
          } catch (parseError) {
            logger.error('[autoUpdater] 解析latest.yml出错:', parseError);
            throw new Error('解析更新信息失败: ' + parseError.message);
          }
        })
        .catch(err => {
          logger.error('[autoUpdater] 获取latest.yml失败:', err);
          
          // 如果手动检查失败，尝试使用autoUpdater的方法
          logger.info('[autoUpdater] 尝试使用自动更新器方法');
          // 调用检查更新
          autoUpdater.checkForUpdates()
            .then(checkResult => {
              logger.info('[autoUpdater] 检查结果:', checkResult);
            })
            .catch(autoUpdateErr => {
              logger.error('[autoUpdater] 自动更新检查失败:', autoUpdateErr);
              
              this.sendStatusToWindow({
                status: -1,
                desc: '检查更新失败: ' + err.message,
                error: err.stack || '未知错误'
              });
            });
        });
    } catch (err) {
      logger.error('[autoUpdater] 检查更新时发生错误:', err);
      this.sendStatusToWindow({
        status: -1,
        desc: '检查更新出错: ' + (err.message || String(err)),
        error: err.stack || '未知错误'
      });
    }
  }
  
  /**
   * 获取latest.yml文件内容
   * @param {string} url - latest.yml文件的URL
   * @returns {Promise<string>} - 返回文件内容
   */
  fetchLatestYml(url) {
    return new Promise((resolve, reject) => {
      const http = require('http');
      const https = require('https');
      
      logger.info('[autoUpdater] 获取更新文件:', url);
      
      const urlObj = new URL(url);
      const httpModule = urlObj.protocol === 'https:' ? https : http;
      
      const req = httpModule.get(url, (res) => {
        if (res.statusCode !== 200) {
          reject(new Error(`获取更新信息失败，状态码: ${res.statusCode}`));
          return;
        }
        
        let data = '';
        res.setEncoding('utf8');
        res.on('data', (chunk) => {
          data += chunk;
        });
        
        res.on('end', () => {
          resolve(data);
        });
      });
      
      req.on('error', (err) => {
        reject(err);
      });
      
      req.setTimeout(10000, () => {
        req.abort();
        reject(new Error('获取更新信息超时'));
      });
      
      req.end();
    });
  }
  
  /**
   * 比较版本号，判断newVersion是否比currentVersion更新
   * @param {string} newVersion - 新版本号
   * @param {string} currentVersion - 当前版本号
   * @returns {boolean} - 如果newVersion比currentVersion更新，返回true
   */
  isVersionNewer(newVersion, currentVersion) {
    if (!newVersion || !currentVersion) return false;
    
    const parseVersion = (version) => {
      const parts = version.split('.');
      return parts.map(part => parseInt(part, 10));
    };
    
    const newParts = parseVersion(newVersion);
    const currentParts = parseVersion(currentVersion);
    
    // 确保两个版本号都有相同数量的部分
    while (newParts.length < currentParts.length) newParts.push(0);
    while (currentParts.length < newParts.length) currentParts.push(0);
    
    // 比较每一部分
    for (let i = 0; i < newParts.length; i++) {
      if (newParts[i] > currentParts[i]) return true;
      if (newParts[i] < currentParts[i]) return false;
    }
    
    return false; // 如果所有部分都相等，则不是更新版本
  }
  
  /**
   * 下载更新
   */
  download () {
    try {
      logger.info('[autoUpdater] 开始下载更新');
      logger.info('[autoUpdater] 更新服务器URL:', this.config.options.url);
      
      // 发送开始下载的状态到窗口
      this.sendStatusToWindow({
        status: 3, // 下载状态码
        desc: '开始下载更新...',
        percentNumber: 0,
        url: this.config.options.url
      });
      
      // 手动获取yaml信息并下载
      this.fetchLatestYml(this.config.options.url + 'latest.yml')
        .then(ymlContent => {
          try {
            const yaml = require('js-yaml');
            const updateInfo = yaml.load(ymlContent);
            
            // 检查文件信息是否存在
            if (!updateInfo.files || !updateInfo.files.length) {
              throw new Error('更新信息中没有文件信息');
            }
            
            // 获取第一个文件的URL
            const fileInfo = updateInfo.files[0];
            
            // 检查URL是否已经是完整路径
            let fileUrl = fileInfo.url;
            if (!fileUrl.startsWith('http')) {
              fileUrl = this.config.options.url + fileInfo.url;
            }
            
            logger.info('[autoUpdater] 下载文件:', fileUrl);
            
            // 使用autoUpdater下载
            this.startDownload(fileInfo);
          } catch (parseError) {
            logger.error('[autoUpdater] 解析latest.yml出错:', parseError);
            this.sendStatusToWindow({
              status: -1,
              desc: '解析更新信息失败: ' + parseError.message,
              error: parseError.stack
            });
          }
        })
        .catch(err => {
          logger.error('[autoUpdater] 获取latest.yml失败:', err);
          
          // 如果手动获取失败，尝试使用autoUpdater的方法
          logger.info('[autoUpdater] 尝试使用自动更新器下载');
          try {
            autoUpdater.downloadUpdate()
              .then(() => {
                logger.info('[autoUpdater] 下载开始');
              })
              .catch(downloadErr => {
                logger.error('[autoUpdater] 下载失败:', downloadErr);
                this.sendStatusToWindow({
                  status: -1,
                  desc: '下载失败: ' + downloadErr.message,
                  error: downloadErr.stack
                });
              });
          } catch (autoUpdateErr) {
            logger.error('[autoUpdater] 启动下载失败:', autoUpdateErr);
            this.sendStatusToWindow({
              status: -1,
              desc: '启动下载失败: ' + autoUpdateErr.message,
              error: autoUpdateErr.stack
            });
          }
        });
    } catch (err) {
      logger.error('[autoUpdater] 下载更新时发生错误:', err);
      this.sendStatusToWindow({
        status: -1,
        desc: '下载更新出错: ' + (err.message || String(err)),
        error: err.stack || '未知错误'
      });
    }
  }

  /**
   * 开始下载更新文件
   * @param {Object} fileInfo - 文件信息对象
   */
  startDownload(fileInfo) {
    try {
      // 使用autoUpdater的downloadUpdate方法
      logger.info('[autoUpdater] 使用electron-updater下载更新');
      autoUpdater.downloadUpdate();
    } catch (err) {
      logger.error('[autoUpdater] 开始下载失败:', err);
      this.sendStatusToWindow({
        status: -1,
        desc: '开始下载失败: ' + err.message,
        error: err.stack
      });
    }
  }

  /**
   * 向前端发消息
   */
  sendStatusToWindow(content = {}) {
    const textJson = JSON.stringify(content);
    const channel = 'custom/app/updater';
    const win = getMainWindow();
    win.webContents.send(channel, textJson);
  }
  
  /**
   * 单位转换
   */
  bytesChange (limit) {
    let size = "";
    if(limit < 0.1 * 1024){                            
      size = limit.toFixed(2) + "B";
    }else if(limit < 0.1 * 1024 * 1024){            
      size = (limit/1024).toFixed(2) + "KB";
    }else if(limit < 0.1 * 1024 * 1024 * 1024){        
      size = (limit/(1024 * 1024)).toFixed(2) + "MB";
    }else{                                            
      size = (limit/(1024 * 1024 * 1024)).toFixed(2) + "GB";
    }

    let sizeStr = size + "";                        
    let index = sizeStr.indexOf(".");                    
    let dou = sizeStr.substring(index + 1 , index + 3);            
    if(dou == "00"){
        return sizeStr.substring(0, index) + sizeStr.substring(index + 3, index + 5);
    }

    return size;
  }  
}
AutoUpdaterService.toString = () => '[class AutoUpdaterService]';

module.exports = {
  autoUpdaterService: new AutoUpdaterService()
};